// Inheritance (继承) 示例
// 演示 Pascal 中继承的各种用法
program p_29_inheritance;

{$mode objfpc}{$H+}
// {$mode objfpc} 启用 Object Pascal 模式，支持面向对象编程
// {$H+} 启用长字符串支持（AnsiString）

// 引入单元文件
uses
  SysUtils;  // 系统工具单元，包含常用的系统函数

// 定义基类：动物
type
  TAnimal = class
  protected
    FName: String;
    FAge: Integer;
  public
    constructor Create(const AName: String; AAge: Integer);
    procedure MakeSound; virtual;
    procedure ShowInfo;
    property Name: String read FName;
    property Age: Integer read FAge;
  end;

// TAnimal类的实现
constructor TAnimal.Create(const AName: String; AAge: Integer);
begin
  inherited Create;
  FName := AName;
  FAge := AAge;
  WriteLn('  创建动物: ', FName);
end;

procedure TAnimal.MakeSound;
begin
  WriteLn('  动物发出声音');
end;

procedure TAnimal.ShowInfo;
begin
  WriteLn('  名称: ', FName, ', 年龄: ', FAge, '岁');
end;

// 定义派生类：狗（继承自动物）
type
  TDog = class(TAnimal)
  private
    FBreed: String;  // 品种
  public
    constructor Create(const AName: String; AAge: Integer; const ABreed: String);
    procedure MakeSound; override;
    procedure WagTail;
    property Breed: String read FBreed;
  end;

// TDog类的实现
constructor TDog.Create(const AName: String; AAge: Integer; const ABreed: String);
begin
  inherited Create(AName, AAge);  // 调用父类构造函数
  FBreed := ABreed;
  WriteLn('  创建狗: ', FName, ', 品种: ', FBreed);
end;

procedure TDog.MakeSound;
begin
  WriteLn('  ', FName, ' 汪汪叫');
end;

procedure TDog.WagTail;
begin
  WriteLn('  ', FName, ' 摇尾巴');
end;

// 定义派生类：猫（继承自动物）
type
  TCat = class(TAnimal)
  private
    FColor: String;  // 颜色
  public
    constructor Create(const AName: String; AAge: Integer; const AColor: String);
    procedure MakeSound; override;
    procedure Purr;
    property Color: String read FColor;
  end;

// TCat类的实现
constructor TCat.Create(const AName: String; AAge: Integer; const AColor: String);
begin
  inherited Create(AName, AAge);  // 调用父类构造函数
  FColor := AColor;
  WriteLn('  创建猫: ', FName, ', 颜色: ', FColor);
end;

procedure TCat.MakeSound;
begin
  WriteLn('  ', FName, ' 喵喵叫');
end;

procedure TCat.Purr;
begin
  WriteLn('  ', FName, ' 发出呼噜声');
end;

// 定义派生类：工作犬（继承自狗）
type
  TWorkingDog = class(TDog)
  private
    FJob: String;  // 工作类型
  public
    constructor Create(const AName: String; AAge: Integer; const ABreed: String; const AJob: String);
    procedure MakeSound; override;
    procedure Work;
    property Job: String read FJob;
  end;

// TWorkingDog类的实现
constructor TWorkingDog.Create(const AName: String; AAge: Integer; const ABreed: String; const AJob: String);
begin
  inherited Create(AName, AAge, ABreed);  // 调用父类构造函数
  FJob := AJob;
  WriteLn('  创建工作犬: ', FName, ', 工作: ', FJob);
end;

procedure TWorkingDog.MakeSound;
begin
  WriteLn('  ', FName, ' 汪汪叫（工作犬）');
end;

procedure TWorkingDog.Work;
begin
  WriteLn('  ', FName, ' 正在执行 ', FJob, ' 工作');
end;

// 程序主入口
begin
  WriteLn('=== Pascal 继承示例 ===');
  WriteLn;
  
  // 1. 创建基类对象
  WriteLn('1. 创建基类对象:');
  var animal: TAnimal := TAnimal.Create('普通动物', 5);
  try
    animal.ShowInfo;
    animal.MakeSound;
  finally
    animal.Free;
  end;
  
  WriteLn;
  
  // 2. 创建派生类对象
  WriteLn('2. 创建派生类对象:');
  var dog: TDog := TDog.Create('小白', 3, '金毛');
  try
    dog.ShowInfo;  // 继承的方法
    WriteLn('  品种: ', dog.Breed);
    dog.MakeSound;  // 重写的方法
    dog.WagTail;    // 自己的方法
  finally
    dog.Free;
  end;
  
  WriteLn;
  
  // 3. 创建另一个派生类对象
  WriteLn('3. 创建另一个派生类对象:');
  var cat: TCat := TCat.Create('小花', 2, '橘色');
  try
    cat.ShowInfo;  // 继承的方法
    WriteLn('  颜色: ', cat.Color);
    cat.MakeSound;  // 重写的方法
    cat.Purr;       // 自己的方法
  finally
    cat.Free;
  end;
  
  WriteLn;
  
  // 4. 多层继承
  WriteLn('4. 多层继承:');
  var workingDog: TWorkingDog := TWorkingDog.Create('警犬一号', 4, '德国牧羊犬', '巡逻');
  try
    workingDog.ShowInfo;  // 继承自TAnimal的方法
    WriteLn('  品种: ', workingDog.Breed);
    WriteLn('  工作: ', workingDog.Job);
    workingDog.MakeSound;  // 重写的方法
    workingDog.WagTail;    // 继承自TDog的方法
    workingDog.Work;       // 自己的方法
  finally
    workingDog.Free;
  end;
  
  WriteLn;
  
  // 5. 多态性演示
  WriteLn('5. 多态性演示:');
  var animals: array[1..4] of TAnimal;
  
  animals[1] := TAnimal.Create('动物基类', 1);
  animals[2] := TDog.Create('旺财', 3, '哈士奇');
  animals[3] := TCat.Create('咪咪', 2, '黑白相间');
  animals[4] := TWorkingDog.Create('搜救犬', 5, '拉布拉多', '搜救');
  
  try
    for var i := 1 to 4 do
    begin
      WriteLn('  对象 ', i, ':');
      animals[i].ShowInfo;
      animals[i].MakeSound;  // 多态：调用各自重写的方法
      
      // 类型检查和转换
      if animals[i] is TDog then
      begin
        WriteLn('    这是一只狗');
        TDog(animals[i]).WagTail;
      end;
      
      if animals[i] is TCat then
      begin
        WriteLn('    这是一只猫');
        TCat(animals[i]).Purr;
      end;
      
      if animals[i] is TWorkingDog then
      begin
        WriteLn('    这是一只工作犬');
        TWorkingDog(animals[i]).Work;
      end;
      
      WriteLn;
    end;
  finally
    // 释放所有对象
    for var i := 1 to 4 do
      animals[i].Free;
  end;
  
  WriteLn;
  
  // 6. 访问父类成员
  WriteLn('6. 访问父类成员:');
  var myDog: TDog := TDog.Create('豆豆', 1, '泰迪');
  try
    WriteLn('  狗的名字（继承的属性）: ', myDog.Name);
    WriteLn('  狗的年龄（继承的属性）: ', myDog.Age);
    WriteLn('  狗的品种（自己的属性）: ', myDog.Breed);
    
    WriteLn('  调用继承的方法:');
    myDog.ShowInfo;
    
    WriteLn('  调用重写的方法:');
    myDog.MakeSound;
  finally
    myDog.Free;
  end;
  
  WriteLn;
  WriteLn('演示了 Pascal 中继承的各种用法');
  
  // 等待用户按键，防止程序窗口立即关闭
  ReadLn;
end.